#include "fsl_common.h"
#include "clock.h"
#include "mpu.h"
#include "sdram.h"
#include "beatLED.h"
#include "emmc.h"
#include "usb_composite.h"
#include "sai.h"
#include "codec.h"
#include "timer.h"
#include "counter.h"
#include "io.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"

#include "appCommon.h"
#include "taskUSBTransfe.h"
#include "taskAudioProcessed.h"

TaskHandle_t hUSBTransfe;
TaskHandle_t hAudioProcessed;
TaskHandle_t hAudioPlay;

static void appTask_CreateTask(void *pvParameters);
static void appTask_SystemStatus(void *pvParameters);

#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE > 0)
/*******************************************************************************
 * @brief 复制中断向量表
*******************************************************************************/
void CopyVector(void)
{
#if defined( __CC_ARM ) || defined(__ARMCC_VERSION)
	extern uint32_t Image$$VECTOR_ROM$$Base[];
    extern uint32_t Image$$VECTOR_ROM$$Limit[];
	extern uint32_t Image$$VECTOR_RAM$$Base[];
    void *pS = (void *)Image$$VECTOR_ROM$$Base;
    void *pT = (void *)Image$$VECTOR_RAM$$Base;
    uint32_t vectorTableSize = (uint32_t)Image$$VECTOR_ROM$$Limit - (uint32_t)Image$$VECTOR_ROM$$Base;
#elif defined ( __GNUC__ )
    extern uint32_t __vectors_load_start__[];
    extern uint32_t __vectors_ram_load_start__[];
    void *pS = (void *)__vectors_load_start__;
    void *pT = (void *)__vectors_ram_load_start__;
#elif defined ( __ICCARM__ )
    extern uint32_t __VECTOR_TABLE[];
    extern uint32_t __VECTOR_RAM[];
    void *pS = (void *)__VECTOR_TABLE;
    void *pT = (void *)__VECTOR_RAM;
#endif
    memcpy(pT,pS,vectorTableSize);
}

/*******************************************************************************
 * @brief 设置中断向量表位置
 * @param addr 向量表位置
*******************************************************************************/
void SetVectorAddr(uint32_t addr)
{
	__asm("CPSID I");
	SCB->VTOR = (uint32_t)addr;
	__asm("CPSIE i");
}

#endif

int main(void)
{
#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
#if defined( __CC_ARM ) || defined(__ARMCC_VERSION)
    extern uint32_t Image$$VECTOR_RAM$$Base[];
    uint32_t pRamVectorAddr = (uint32_t)Image$$VECTOR_RAM$$Base;
#elif defined ( __GNUC__ )
    extern uint32_t __vectors_ram_start__[];
    uint32_t pRamVectorAddr = (uint32_t)__vectors_ram_start__;
#elif defined ( __ICCARM__ )
    extern uint32_t __VECTOR_RAM[];
    uint32_t pRamVectorAddr = (uint32_t)__VECTOR_RAM;
#endif
	CopyVector();
	SetVectorAddr(pRamVectorAddr);
#endif
	//NVIC_SetPriorityGrouping();
	mpuInit();
	systemClockInit();
//#if !defined(XIP_BOOT_HEADER_ENABLE) || (XIP_BOOT_HEADER_ENABLE != 1)
#ifndef SKIP_SYSCLK_INIT
	sdramInit();
#endif

    if (xTaskCreate(appTask_CreateTask, appTask_CreateTask_NANE, appTask_CreateTask_STACK_DEPTH, NULL, appTask_CreateTask_PRIORITY, NULL) !=pdPASS)
    {
        while (1);
    }
    vTaskStartScheduler();

    return 0;
}

static void appTask_CreateTask(void *pvParameters)
{
    emmcInit();
    ioInit();
    codecInit();
    codecReset();
    saiInit();
    usbCompositeInit();
    if (xTaskCreate(appTask_SystemStatus, appTask_SystemStatus_NANE, appTask_SystemStatus_STACK_DEPTH, NULL, appTask_SystemStatus_PRIORITY, NULL) !=pdPASS)
    {
        while (1);
    }
    if (xTaskCreate(appTask_USBTransfe, appTask_USBTransfe_NANE, appTask_USBTransfe_STACK_DEPTH, NULL, appTask_USBTransfe_PRIORITY, &hUSBTransfe) !=pdPASS)
    {
        while (1);
    }
    if (xTaskCreate(appTask_AudioProcessed, appTask_AudioProcessed_NANE, appTask_AudioProcessed_STACK_DEPTH, NULL, appTask_AudioProcessed_PRIORITY, &hAudioProcessed) !=pdPASS)
    {
        while (1);
    }
    ioRelayBypassCtrl(0);
    ioMuteCtrl(0);
    vTaskDelete(NULL);
}

static void appTask_SystemStatus(void *pvParameters)
{
    beatLEDInit();
    while(1)
    {
#ifdef RUN_IN_RAM
        beatLEDBright();
        vTaskDelay(pdMS_TO_TICKS(10));
        beatLEDGoOut();
        vTaskDelay(pdMS_TO_TICKS(100));
        beatLEDBright();
        vTaskDelay(pdMS_TO_TICKS(10));
        beatLEDGoOut();
        vTaskDelay(pdMS_TO_TICKS(380));
#else
        beatLEDToggle();
        vTaskDelay(pdMS_TO_TICKS(300));
#endif
    }
}

#if (configSUPPORT_STATIC_ALLOCATION > 0)

/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                    StackType_t **ppxIdleTaskStackBuffer,
                                    uint32_t *pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
function then they must be declared static – otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];

    /* Pass out a pointer to the StaticTask_t structure in which the Idle task’s
    state will be stored. */
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

    /* Pass out the array that will be used as the Idle task’s stack. */
    *ppxIdleTaskStackBuffer = uxIdleTaskStack;

    /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
    Note that, as the array is necessarily of type StackType_t,
    configMINIMAL_STACK_SIZE is specified in words, not bytes. */
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*———————————————————–*/

/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                     StackType_t **ppxTimerTaskStackBuffer,
                                     uint32_t *pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
function then they must be declared static – otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];

    /* Pass out a pointer to the StaticTask_t structure in which the Timer
    task’s state will be stored. */
    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

    /* Pass out the array that will be used as the Timer task’s stack. */
    *ppxTimerTaskStackBuffer = uxTimerTaskStack;

    /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
    Note that, as the array is necessarily of type StackType_t,
    configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}


#endif

void HardFault_Handler(void)
{
    while(1)
    {
        ;
    }
}
